package info.emamian.droplet.core.services;

import info.emamian.droplet.core.domain.BasicSMS;
import info.emamian.droplet.core.smsHandler.AbstractSMSHandler;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class SMSService {
	private Map<String, List<AbstractSMSHandler>> handlers = new HashMap<String, List<AbstractSMSHandler>>();

	public boolean registerHandler(String khandlerKey, AbstractSMSHandler handler) {
		if (khandlerKey == null)
			throw new IllegalArgumentException("hanlder key cannot be null");
		String key = khandlerKey.trim();
		if (key.isEmpty())
			throw new IllegalArgumentException("hanlder key cannot be empty");

		// create handler list for key if not exist
		if (!handlers.containsKey(key)) {
			handlers.put(key, new ArrayList<AbstractSMSHandler>());
		}

		List<AbstractSMSHandler> list = handlers.get(key);
		if (!list.contains(handler))// prevent duplicate
			list.add(handler);
		return true;
	}

	public void unRegisterHandler(String handlerKey, AbstractSMSHandler handler) {
		if (handlerKey == null)
			throw new IllegalArgumentException("hanlder key cannot be null");
		String key = handlerKey.trim();
		if (handlers.containsKey(key)) {
			List<AbstractSMSHandler> list = handlers.get(key);
			list.remove(handler);
		}
	}

	/**
	 * Retrieves best answer from appropriate handler for <code>sms</code> based
	 * on first word of sms
	 * 
	 * @param sms
	 *            input sms that should be handled by appropriate
	 *            <code>AbstractSMSHandler</code>
	 * @return answer to <code>sms</code> or <code>allHandlersUsage</code> if
	 *         first word is a reserved word.
	 */
	public String getAnswerFromAppropriateHandler(BasicSMS sms) {
		if (sms == null || sms.isEmpty())
			return null;
		String first = sms.getFirstWord();
		// check for reserved words e.g. help, cmd
		if (isResevedWord(first)) {
			return getAllHandlersUsage();
		}

		// check handlers for appropriate answer
		if (handlers.containsKey(first)) {
			List<AbstractSMSHandler> listOfHandlers = handlers.get(first);
			for (Iterator<AbstractSMSHandler> iterator = listOfHandlers.iterator(); iterator.hasNext();) {
				AbstractSMSHandler smsHandler = iterator.next();
				if (smsHandler.canAnswer(sms)) {
					String answer = smsHandler.getAnswer();
					if (answer != null && !answer.trim().isEmpty()) {
						return answer;
					}
				}
			}
		}
		// TODO handle other than first word cases

		// no answer found
		return null;
	}

	/**
	 * Check if the <code>word</code> is a reserved word.
	 * 
	 * @param word
	 * @return
	 */
	public boolean isResevedWord(String word) {
		if (word == null)
			return false;
		String w = word.trim();
		return (w.equalsIgnoreCase("help") || w.equalsIgnoreCase("hlp") || w.equalsIgnoreCase("cmd"));
	}

	/**
	 * @return Concatenation of all handlers' usages
	 */
	public String getAllHandlersUsage() {
		String ret = "";
		Collection<List<AbstractSMSHandler>> allHandlers = handlers.values();
		for (Iterator<List<AbstractSMSHandler>> allHandlersIterator = allHandlers.iterator(); allHandlersIterator.hasNext();) {
			List<AbstractSMSHandler> handlersList = (List<AbstractSMSHandler>) allHandlersIterator.next();

			for (Iterator<AbstractSMSHandler> handlerIterator = handlersList.iterator(); handlerIterator.hasNext();) {
				AbstractSMSHandler abstractSMSHandler = (AbstractSMSHandler) handlerIterator.next();
				if (!ret.isEmpty())
					ret += ",";
				ret += abstractSMSHandler.getUsage();
			}
		}
		ret = ret.trim();
		if (ret.isEmpty())
			return null;
		return ret;
	}

	/**
	 * @param handlerKey
	 * @return null or empty string if <code>handlerKey</code> has not handlers
	 */
	public String getAllHandlersUsageForKeyword(String handlerKey) {
		if (handlerKey == null) {
			return null;
		}
		List<AbstractSMSHandler> handlersList = handlers.get(handlerKey);
		if (handlersList == null) {
			return null;
		}
		String ret = "";
		for (Iterator<AbstractSMSHandler> handlerIterator = handlersList.iterator(); handlerIterator.hasNext();) {
			AbstractSMSHandler abstractSMSHandler = (AbstractSMSHandler) handlerIterator.next();
			if (!ret.isEmpty())
				ret += ",";
			ret += abstractSMSHandler.getUsage();
		}
		ret = ret.trim();
		return ret;
	}
}
